#include <iostream>
#include <thread>
#include <mutex>
#include <chrono>
#include <random>

std::mutex mtx;
bool channelBusy = false;
bool collisionDetected = false;

void host(int id) {
    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_int_distribution<> dis(100, 500);

    while (true) {
        std::this_thread::sleep_for(std::chrono::milliseconds(dis(gen)));
        mtx.lock();
        if (channelBusy) {
            std::cout << "Host " << id << " detects channel busy, waiting..." << std::endl;
            mtx.unlock();
            continue;
        }

        channelBusy = true;
        mtx.unlock();

        std::cout << "Host " << id << " starts sending data." << std::endl;

        std::this_thread::sleep_for(std::chrono::milliseconds(200));

        mtx.lock();
        if (collisionDetected) {
            std::cout << "Host " << id << " detects collision, backing off..." << std::endl;
            collisionDetected = false;
            channelBusy = false;
            mtx.unlock();
            std::this_thread::sleep_for(std::chrono::milliseconds(dis(gen)));
        } else {
            std::cout << "Host " << id << " finishes sending data." << std::endl;
            channelBusy = false;
            mtx.unlock();
        }
    }
}

void collisionDetector() {
    while (true) {
        std::this_thread::sleep_for(std::chrono::milliseconds(100));
        mtx.lock();
        if (channelBusy) {
            collisionDetected = true;
        }
        mtx.unlock();
    }
}

int main() {
    std::thread host1(host, 1);
    std::thread host2(host, 2);
    std::thread detector(collisionDetector);

    host1.join();
    host2.join();
    detector.join();

    return 0;
}